package ru.susu.algebra;

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.PrintWriter;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import ru.susu.algebra.chartable.degree.HooksDegreeCalculator;
import ru.susu.algebra.chartable.degree.IDegreeCalculator;
import ru.susu.algebra.partition.Partition;
import ru.susu.algebra.partition.PartitionEnumerator;
import ru.susu.algebra.partition.PartitionsFacade;
import ru.susu.algebra.partition.PartitionsFactory;

/**
 * @author akargapolov
 * @since: 08.09.2009
 */
public class EqualsDegreeFinder
{
	public static void main(String[] args) throws Exception
	{
		IDegreeCalculator hooks = new HooksDegreeCalculator();

		for (int i = 1; i <= 50; i++)
		{
			Date startDate = new Date();

			HashMap<BigInteger, List<Partition>> mp = new HashMap<BigInteger, List<Partition>>();

			Integer length = PartitionEnumerator.getPartitionsNumber(i).intValue();
			boolean served[] = new boolean[length];
			Arrays.fill(served, false);

			for (int j = 0; j < length; j++)
			{
				if (served[j])
					continue;

				Partition p = PartitionsFactory.createPartition(j, i);

				BigInteger degree = hooks.calculateDegree(p);
				if (!mp.containsKey(degree))
					mp.put(degree, new ArrayList<Partition>(1));
				mp.get(degree).add(p);

				served[PartitionsFacade.getAssociatedPartition(p).getOrderNumber()] = true;
				served[j] = true;
			}

			List<BigInteger> degrees = new ArrayList<BigInteger>();
			for (Map.Entry<BigInteger, List<Partition>> entry : mp.entrySet())
				if (entry.getValue().size() > 1)
					degrees.add(entry.getKey());

			Collections.sort(degrees);

			if (degrees.isEmpty())
				continue;

			PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter("ExecuteResults/EqualDegrees/" + i
					+ ".txt")));

			for (BigInteger degree : degrees)
			{
				out.println("Degree: " + degree);
				for (Partition p : mp.get(degree))
				{
					p.writeTo(out, 3);
					out.println();
				}
				out.println();
			}

			Date endDate = new Date();
			out.close();
			System.out.println(i + ": Time " + (endDate.getTime() - startDate.getTime()));
		}
	}
}
